﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TestOnlineProject.Models.Entities;
using TestOnlineProject.Models.BusinessLogic;
using PagedList;

namespace TestOnlineProject.Areas.Admin.Controllers
{
    [Authorize]
    public class SubjectController : Controller
    {
        SubjectBLO subjectBLO = new SubjectBLO();
        UserBLO userBLO = new UserBLO();
        ParticipantBLO participantBLO = new ParticipantBLO();

        //
        // GET: /Admin/Subject/
        public ActionResult Index(int? page, string keyWord = "", string column = "", string sort = "")
        {
            try
            {
                var user = userBLO.Find(int.Parse(HttpContext.User.Identity.Name));
                // Check valid user
                if(user == null)
                {
                    return RedirectToAction("Error", "Account");
                }
                if(!user.IsActivated)
                {
                    return RedirectToAction("Error", "Account");
                }
                // No. list.
                var noList = new List<NoModel>();

                // User list.
                List<Subject> subjects = subjectBLO.ToList(ref noList, page, keyWord, column, sort);

                if (!HttpContext.User.IsInRole("1"))
                {
                    subjects = subjects.Where(s => s.IsActivated).ToList();
                }

                // Sort states.
                ViewBag.KeyWord = keyWord;
                ViewBag.Page = page;
                ViewBag.Column = column;
                ViewBag.Sort = sort;
                ViewBag.Msg = TempData["Msg"] as string;
                ViewBag.NoList = noList;

                // Return.
                var pageNumber = page ?? 1;
                var onePageOfSubjects = subjects.ToPagedList(pageNumber, 10);
                ViewBag.onePageOfSubjects = onePageOfSubjects;
                return Request.IsAjaxRequest()
                    ? (ActionResult)PartialView("_List")
                    : View();
            }
            catch (Exception)
            {
                // Wrtite to log file.
                return RedirectToAction("Index", "Error", new { Area = "" });
            }
        }

        //
        // GET: /Admin/Subject/Create

        [Authorize(Roles = "1")]
        public ActionResult Create()
        {
            var user = userBLO.Find(int.Parse(HttpContext.User.Identity.Name));
            // Check valid user
            if (user == null)
            {
                return RedirectToAction("Error", "Account");
            }
            if (!user.IsActivated)
            {
                return RedirectToAction("Error", "Account");
            }
            return View();
        }

        //
        // POST: /Admin/Subject/Create
        [Authorize(Roles = "1")]
        [HttpPost]
        public ActionResult Create(Subject subject)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    int result = subjectBLO.Add(subject);

                    // Send message to view notify that create successful.
                    if (result > 0)
                    {
                        TempData["Msg"] = "New subject has been created.";
                        return RedirectToAction("Details", new { id = subject.SubjectId });
                    }
                    else if (result == -1)
                    {
                        ModelState.AddModelError("", "Duplicate Code.");
                    }
                    else
                    {
                        ModelState.AddModelError("", "An error occurred.");
                    }
                }
                return View(subject);
            }
            catch (Exception)
            {
                // Write to log file.
                return RedirectToAction("Index", "Error", new { Area = "" });
            }
        }

        //
        // GET: /Admin/Subject/Details/5

        public ActionResult Details(int id = 0)
        {
            try
            {
                var user = userBLO.Find(int.Parse(HttpContext.User.Identity.Name));
                // Check valid user
                if (user == null)
                {
                    return RedirectToAction("Error", "Account");
                }
                if (!user.IsActivated)
                {
                    return RedirectToAction("Error", "Account");
                }
                var subject = subjectBLO.Find(id);

                // Authorize
                if (subject == null)
                {
                    return HttpNotFound();
                }
                
                if (!HttpContext.User.IsInRole("1"))
                {
                    if (!participantBLO.CheckParticipant(int.Parse(HttpContext.User.Identity.Name), id))
                    {
                        TempData["Msg"] = "You can not access this subject. Please contact Admin to more details.";
                        return RedirectToAction("Index");
                    }
                }

                //Send message to views. The message passed by some action.
                ViewBag.Msg = TempData["Msg"] as string;
                return View(subject);
            }
            catch (Exception)
            {
                // Write to log file.
                return RedirectToAction("Index", "Error", new { Area = "" });
            }
        }

        //
        // GET: /Admin/Subject/Edit
        [Authorize(Roles = "1")]
        public ActionResult Edit(int id = 0)
        {
            try
            {
                var user = userBLO.Find(int.Parse(HttpContext.User.Identity.Name));
                // Check valid user
                if (user == null)
                {
                    return RedirectToAction("Error", "Account");
                }
                if (!user.IsActivated)
                {
                    return RedirectToAction("Error", "Account");
                }
                // check valid subject
                var subject = subjectBLO.Find(id);
                if (subject == null)
                {
                    return HttpNotFound();
                }
                return View(subject);
            }
            catch (Exception)
            {
                // Write to log file.
                return RedirectToAction("Index", "Error", new { Area = "" });
            }
        }

        //
        // POST: /Admin/Subject/Edit/5
        [Authorize(Roles = "1")]
        [HttpPost]
        public ActionResult Edit(Subject subject)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    int result = subjectBLO.Modify(subject);
                    if (result > 0)
                    {
                        TempData["Msg"] = "The subject has been updated.";
                        return RedirectToAction("Details", new { id = subject.SubjectId });
                    }
                    else
                    {
                        ModelState.AddModelError("", "An error occurred.");
                    }
                }
                return View(subject);
            }
            catch (Exception)
            {
                // Write to log file.
                return RedirectToAction("Index", "Error");
            }
        }

        //
        // GET: /Admin/Subject/Deactivate
        [Authorize(Roles = "1")]
        public string Deactivate(string ids = "")
        {
            try
            {
                int result = subjectBLO.Deactivate(ids);
                if (result > 0)
                {
                    return result + " subject(s) has been deactivated.";
                }
                else
                {
                    return "Subject(s) has been deactivated.";
                }
            }
            catch (Exception)
            {
                // Write to log file.
                return "An error occurred.";
            }
        }

        //
        // GET: /Admin/Subject/Activate
        [Authorize(Roles = "1")]
        public string Activate(string ids = "")
        {
            try
            {
                int result = subjectBLO.Activate(ids);
                if (result > 0)
                {
                    return result + " subject(s) has been activated.";
                }
                else
                {
                    return "Subject(s) has been activated.";
                }
            }
            catch (Exception)
            {
                // Write to log file.
                return "An error occurred.";
            }
        }

        [Authorize(Roles = "1")]
        public string Delete(string ids = "")
        {
            try
            {
                int result = subjectBLO.Remove(ids);
                if (result > 0)
                {
                    return result + " subject(s) has been deleted.";
                }
                else
                {
                    return "An error occurred.";
                }
            }
            catch (Exception)
            {
                // Write to log file.
                return "An error occurred.";
            }
        }

        //
        // GET: /Admin/Subject/Import
        [Authorize(Roles = "1")]
        public ActionResult Import()
        {
            var user = userBLO.Find(int.Parse(HttpContext.User.Identity.Name));
            // Check valid user
            if (user == null)
            {
                return RedirectToAction("Error", "Account");
            }
            if (!user.IsActivated)
            {
                return RedirectToAction("Error", "Account");
            }
            return View();
        }

        //
        // POST: 
        [Authorize(Roles = "1")]
        [HttpPost]
        public ActionResult Import(HttpPostedFileBase file)
        {
            try
            {
                var fileUpload = Request.Files["FileUpload"];

                if (fileUpload != null && fileUpload.ContentLength > 0)
                {
                    string saveFile = "~/ResourceFiles/" + fileUpload.FileName;
                    fileUpload.SaveAs(Server.MapPath(saveFile));
                    string connectionString;
                    if (Path.GetExtension(fileUpload.FileName) == ".xlsx")
                    {
                        connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0 Xml; IMEX = 1\"",
                                      Server.MapPath(saveFile));
                    }
                    else if (Path.GetExtension(fileUpload.FileName) == ".xls")
                    {
                        connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=\"Excel 8.0; IMEX =1\"",
                                      Server.MapPath(saveFile));
                    }
                    else
                    {
                        return new JsonResult()
                        {
                            Data = new
                            {
                                success = false,
                                error = "Please import by Excel Workbook file!"
                            }
                        };
                    }

                    var tuple = subjectBLO.ParseFile(connectionString, Server.MapPath(saveFile));
                    bool fatalError = tuple.Item4;
                    if (fatalError)
                    {
                        return new JsonResult()
                        {
                            Data = new
                            {
                                success = false,
                                error = "Please download template to have an exactly format."
                            }
                        };
                    }

                    Session["ListSubject"] = tuple.Item1;
                    Session["numSuccess"] = tuple.Item2;
                    Session["numFail"] = tuple.Item3;
                    if (tuple.Item5)
                    {
                        return new JsonResult()
                        {
                            Data = new { success = true, error = "Out of time! Please separate your file to import faster!" }
                        };
                    }
                    return new JsonResult()
                    {
                        Data = new
                        {
                            success = true,
                            error = ""
                        }
                    };
                }
                return new JsonResult()
                {
                    Data = new
                    {
                        success = false,
                        error = "Please select the file."
                    }
                };
            }
            catch (Exception e)
            {
                // Write to log file.
                return new JsonResult()
                {
                    Data = new
                    {
                        success = false,
                        error = e.Message
                    }
                };
            }
        }

        //
        // Get: /Admin/Subject/DownloadFile
        [Authorize(Roles = "1")]
        public ActionResult Download()
        {
            return new DownloadModel
            {
                VirtualPath = "~/ResourceFiles/Template/Template_ImportSubjects.xlsx",
                FileDownLoadName = "Template_ImportSubjects.xlsx"
            };
        }

        //
        // GET: /Admin/Subject/Result
        [Authorize(Roles = "1")]
        public ActionResult ImportResult()
        {
            var user = userBLO.Find(int.Parse(HttpContext.User.Identity.Name));
            // Check valid user
            if (user == null)
            {
                return RedirectToAction("Error", "Account");
            }
            if (!user.IsActivated)
            {
                return RedirectToAction("Error", "Account");
            }
            if (Session["ListSubject"] != null)
            {
                var listSubject = (List<SubjectErrorModel>)Session["ListSubject"];
                ViewBag.ListSubject = listSubject;
            }
            if (Session["numSuccess"] != null)
            {
                var num = (int)Session["numSuccess"];
                ViewBag.Success = num;
            }
            if (Session["numFail"] != null)
            {
                var num = (int)Session["numFail"];
                ViewBag.Fail = num;
            }

            return View();
        }
    }
}
